package com.zs.toolbox.web2j.auth.security;

import com.zs.toolbox.web2j.auth.exception.WtTokenExceptionWt;
import com.zs.toolbox.web2j.auth.utils.WtTokenUtils;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.MalformedJwtException;
import io.jsonwebtoken.SignatureException;
import io.jsonwebtoken.UnsupportedJwtException;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashSet;

import static com.zs.toolbox.web2j.auth.contants.WtSecurityConstant.TokenFieldName;

/**
 * token的校验
 * 该类继承自BasicAuthenticationFilter，在doFilterInternal方法中，
 * 从http头的token 项读取token数据，然后用Jwts包提供的方法校验token的合法性。
 * 如果校验通过，就认为这是一个取得授权的合法请求
 *
 * @author zhaoxinguo on 2017/9/13.
 */

public class WtJWTAuthenticationFilter extends BasicAuthenticationFilter {

    public WtJWTAuthenticationFilter(AuthenticationManager authenticationManager) {
        super(authenticationManager);
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {

        try {
            UsernamePasswordAuthenticationToken authentication = getAuthentication(request);
            if(authentication != null) {
                SecurityContextHolder.getContext().setAuthentication(authentication);
            }
            chain.doFilter(request, response);

        }catch (WtTokenExceptionWt e) {
            chain.doFilter(request, response);
        }
    }

    private UsernamePasswordAuthenticationToken getAuthentication(HttpServletRequest request) {
        try {
            String token = null;

            if(token == null) {
                if (request.getParameter(TokenFieldName) != null) {
                    token = request.getParameter(TokenFieldName);
                }
            }

            if(token == null) {
                token = request.getHeader(TokenFieldName);

//                for (Cookie cookie : request.getCookies()) {
//                    if(cookie.getName().equals(TokenFieldName)) {
//                        token = cookie.getValue();
//                    }
//                }
            }

            if (token != null) {
                // parse the token.
                String decodeUserInfo = WtTokenUtils.parseToken(token);

                HashSet<GrantedAuthority> grantedAuthorities = new HashSet<>();

                /*
                 *   获得用户的权限
                 * */
                String[] userData = decodeUserInfo.split("-");
                if (userData.length > 1) {
                    String[] authorityStrings = userData[1].split(",");
                    for (String authorityString : authorityStrings) {
                        grantedAuthorities.add(new SimpleGrantedAuthority(authorityString));
                    }
                }
                return new UsernamePasswordAuthenticationToken(userData[0], null, grantedAuthorities);
            }
        } catch (ExpiredJwtException e) {
            logger.debug("Token已过期: {} " + e);
            throw new WtTokenExceptionWt("Token已过期");
        } catch (UnsupportedJwtException e) {
            logger.debug("Token格式错误: {} " + e);
            throw new WtTokenExceptionWt("Token格式错误");
        } catch (MalformedJwtException e) {
            logger.debug("Token没有被正确构造: {} " + e);
            throw new WtTokenExceptionWt("Token没有被正确构造");
        } catch (SignatureException e) {
            logger.debug("签名失败: {} " + e);
            throw new WtTokenExceptionWt("签名失败");
        } catch (IllegalArgumentException e) {
            logger.debug("非法参数异常: {} " + e);
            throw new WtTokenExceptionWt("非法参数异常");
        }

        return null;
    }


}
